from typing import Tuple, List, Any

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.engine.base import Engine
from sqlalchemy.orm.session import Session
from sqlalchemy.orm.query import Query

import settings
from db.models import Base, Shipping
from scraper.utils import ShippingData



def get_engine_and_session_of_db() -> Tuple[Engine, Session]:
    """ Получаем объекты session и engine для работы с базой данных """

    record_connect_to_db = '{}+{}://{}:{}@{}/{}'.format(
         settings.DIALECT_DB,
         settings.DRIVER_DB,
         settings.POSTGRES_USER,
         settings.POSTGRES_PASSWORD,
         settings.POSTGRES_HOST,
         settings.POSTGRES_NAME
    )
    engine = create_engine(record_connect_to_db)
    Session = sessionmaker(bind=engine)
    session = Session()
    return (engine, session)


def close_engine_and_session_of_db(engine: Engine, session: Session) -> None:
    """ Завершаем работу с базой данных """

    session.close()
    engine.dispose()


def create_necessary_data_in_db(engine: Engine) -> None:
    """ Создаем необходимые данные в бд """

    Base.metadata.create_all(engine)


def filter_new_shipments(
    session: Session,
    list_of_shipments: List[ShippingData]
) -> List[ShippingData]:
    """ Отфильтровываем новые перевозки """

    list_of_new_shipments: List[ShippingData] = []
    _, session = get_engine_and_session_of_db()

    for shipping in list_of_shipments:
        query: Query = session.query(Shipping).filter_by(**shipping)
        is_shippings: bool = session.query(query.exists()).scalar()

        if not is_shippings:
            list_of_new_shipments.append(shipping)

    return list_of_new_shipments


def add_shipping(session: Session, shipping: ShippingData) -> None:
    """ Добавляем перевозку """

    new_shipping: Shipping = Shipping(**shipping)
    session.add(new_shipping)
    session.commit()


def add_list_of_shipments(
    session: Session,
    list_of_shipments: List[ShippingData]
) -> None:
    """ Добавляем список перевозок """

    _ = [add_shipping(session, shipping) for shipping in list_of_shipments]
